/***************************************************************************************
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
*
* NEMU is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*          http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*
* See the Mulan PSL v2 for more details.
***************************************************************************************/

#include <isa.h>
#include "local-include/reg.h"
#include <macro.h>

const char* regs[] = {
    "$0", "ra", "sp",  "gp",  "tp", "t0", "t1", "t2",
    "s0", "s1", "a0",  "a1",  "a2", "a3", "a4", "a5",
    "a6", "a7", "s2",  "s3",  "s4", "s5", "s6", "s7",
    "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6"
};

void isa_reg_display() {
    printf(ANSI_FMT("============================= <Register> =============================\n", ANSI_FG_MAGENTA));
    printf("General Register: \n");
    for (int i = 0; i < ARRLEN(regs); ++i) {
        printf("\t%-3s: " FMT_WORD "\t", regs[i], gpr(i));
        if ((i+1)%2 == 0) printf("\n");
    }
    printf("Control and Status Register: \n");
    printf("\t%-3s: " FMT_WORD "\t\n", "mstatus", cpu.csr.mstatus.value);
    printf("\t%-3s: " FMT_WORD "\t\n", "mie", cpu.csr.mie.value);
    printf("\t%-3s: " FMT_WORD "\t\n", "mtvec", cpu.csr.mtvec.value);
    printf("\t%-3s: " FMT_WORD "\t\n", "mepc", cpu.csr.mepc.value);
    printf("\t%-3s: " FMT_WORD "\t\n", "mcause", cpu.csr.mcause.value);
    printf("\t%-3s: " FMT_WORD "\t\n", "mip", cpu.csr.mip.value);
    
    printf("Program Counter Register: \n");
    printf("\t%-3s: " FMT_WORD "\t\n", "pc", cpu.pc);
    printf(ANSI_FMT("============================= <Register> =============================\n\n", ANSI_FG_MAGENTA));
}

word_t isa_reg_str2val(const char* s, bool* success) {
    // $0
    if (strcmp(s, regs[0]) == 0) return gpr(0);
    // $pc
    if (strcmp(s, "$pc") == 0) return cpu.pc;
    // others
    for (int i = 1; i < ARRLEN(regs); ++i) {
        if (strcmp(regs[i], s+1) == 0) return gpr(i);
    }
    printf("Unknown register: %s\n", s);
    *success = false;
    return -1;
}
